package pathways;

/**
 * Title:        Pathways
 * Description:  Pure Java version of the Pathways Project.
 * Copyright:    Copyright (c) 2002
 * Company:      Ants Technologies
 * @author Veejay Sani
 * @version 1.0
 */

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
import java.util.LinkedList;
import java.util.Vector;

import pathways.util.CUtil;

public class CPathwayPainter implements IPathwayPainter
{
  public CPathwayPainter(ISubstratePainter s, IEnzymePainter e)
  {
    setPainters(s,e);
    extraRectToDraw = null;
    extraRectFillColor = null;
  }
  
  public void setExtraRectToDraw(Rectangle rect, Color c)
  {
    extraRectToDraw = rect;
    extraRectFillColor = c;  
  }
  
  public void setPainters(ISubstratePainter s, IEnzymePainter e)
  {
    substratePainter = s;
    enzymePainter = e;
  }

  public void draw(Graphics graphics, CPathway pathway)
  {
    adjustForNegativeCoords(pathway);
    
    Dimension dimension = getSizeRequired(pathway);
    pathway.getGUIComponent().setSize(dimension);
    
    Vector substrateList = pathway.getSubstrateList();
    Vector reactions = pathway.getReactions();
    LinkedList list = null;
    CSubstrate sub = null;
    CEnzyme enzyme = null;
    CReaction rxn = null;
    
    Component component = pathway.getGUIComponent();

    Dimension d = component.getSize();
    Image offScreenImage = component.createImage(d.width,d.height);
    Graphics offScreenGraphics = offScreenImage.getGraphics();

    for (int i = 0; i < substrateList.size(); i++)
    {
      list = (LinkedList)substrateList.get(i);
      sub = (CSubstrate)list.getFirst();

      sub.draw(offScreenGraphics,substratePainter);
    }

    for (int i = 0; i < reactions.size(); i++)
    {
      rxn = (CReaction)reactions.get(i);
      enzyme = rxn.getEnzyme();
      
      Color lcolor = offScreenGraphics.getColor();
      
      if (CUtil.isBindingProteinReaction(rxn))
      {
        offScreenGraphics.setColor(Color.red);
      }
      
      if (CUtil.isMissingInfoReaction(rxn))
      {
        offScreenGraphics.setColor(new Color(0,170,0));  
      }
      
      enzyme.setPainter(enzymePainter);
      enzyme.draw(offScreenGraphics,enzymePainter);
      
      offScreenGraphics.setColor(lcolor);
    }
    
    for (int i = 0; i < pathway.getSubstratesAsEnzymes().size(); i++)
    {
      CSubstrateAsEnzyme subAsEnzyme = (CSubstrateAsEnzyme)pathway.getSubstratesAsEnzymes().get(i);
      subAsEnzyme.setPainter(enzymePainter);
      
      subAsEnzyme.draw(offScreenGraphics,enzymePainter);
    }
    
    drawExtraRect(offScreenGraphics);
      
    graphics.drawImage(offScreenImage,0,0,component);
  }

  private void drawExtraRect(Graphics g)
  {
    if (extraRectToDraw != null && extraRectFillColor != null)
    {
      Color color = g.getColor();
      g.setColor(extraRectFillColor);
      g.fillRect(extraRectToDraw.x,extraRectToDraw.y,extraRectToDraw.width,extraRectToDraw.height);
      g.setColor(color);
    }
  }
  
  private void adjustForNegativeCoords(CPathway pathway)
  {
    // detect how much negative
    Point adjustments = getAdjustment(pathway);
    
    //System.out.println(adjustments.toString());
    
    // adjust all Substrates by that much amount
    movePathway(pathway,adjustments.x,adjustments.y);
  }
  
  private Dimension getSizeRequired(CPathway pathway)
  {
    // assumes that no negative cooordinates exist

    Vector substrates = pathway.getSubstrateList();
    CSubstrate sub;
    CCoOrdinates coords;
    Point rightMostPoint;
    Point bottomMostPoint;
    int largestX = 0;
    int largestY = 0;
    
    for (int i=0; i<substrates.size(); i++)
    {
      sub = (CSubstrate)((LinkedList)substrates.get(i)).getFirst();
      
      if (sub.isVisible())
      {
        coords = sub.getCoOrdinates();
        rightMostPoint = coords.getPoint2();
        bottomMostPoint = coords.getPoint3();
        
        if (rightMostPoint.x > largestX)
          largestX = rightMostPoint.x;
          
        if (bottomMostPoint.y > largestY)
          largestY = bottomMostPoint.y;
      }
    }
    
    return new Dimension(largestX+10,largestY+10);  
  }
  
  private Point getAdjustment(CPathway pathway)
  {
    // looks only at stuff that is visible
    
    Vector substrates = pathway.getSubstrateList();
    CSubstrate sub;
    CCoOrdinates coords;
    Point leftMostPoint;
    Point topMostPoint;

    int dx = 0;
    int dy = 0;

    for (int i=0; i<substrates.size(); i++)
    {
      sub = (CSubstrate)((LinkedList)substrates.get(i)).getFirst();
      
      if (sub.isVisible())
      {
        coords = sub.getCoOrdinates();
        leftMostPoint = coords.getPoint0();
        topMostPoint = coords.getPoint1();

        if (leftMostPoint.x < dx)
          dx = leftMostPoint.x;
          
        if (topMostPoint.y < dy)
          dy = topMostPoint.y;
      }
    }
    
    return new Point(-dx,-dy);
  }
  
  private void movePathway(CPathway pathway, int dx, int dy)
  {
    // only need to adjust substrates
    // because enzymes just join substrates
    // only moves the visible substrates
    
    Vector substrates =  pathway.getSubstrateList();
    CSubstrate sub;
    
    for (int i=0; i<substrates.size(); i++)
    {
      sub = (CSubstrate)((LinkedList)substrates.get(i)).getFirst();
      
      if (sub.isVisible())   
      {
        sub.getCoOrdinates().moveRect(dx,dy);       
      }
    }
  }
  
  private ISubstratePainter substratePainter;
  private IEnzymePainter enzymePainter;
  private Rectangle extraRectToDraw;
  private Color extraRectFillColor;
}